package com.jade.editor.domain.obj;

import java.awt.Polygon;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.wb.swt.SWTResourceManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class ObjectModel {
	
	public static final int LOAD_OK = 0;
	public static final int LOAD_FAIL = 1;
	public static final int LOAD_NO = 2;
	
	private String _aniType = "";
	private boolean _hasAni = false;
	private int _load = LOAD_NO;
	
	private ArrayList<Point> _shelllist = new ArrayList<Point>();
	private ArrayList<Point> _alist = new ArrayList<Point>();
	private double _angle = 0.0;
	
	private RGB _color = new RGB(0,0,0);
	
	private File _objFile = null;
	
	
	
	
	
	public double getAngle(){
		return _angle;
	}
	
	public ObjectModel(String path){
		_objFile = new File(path);
		load();
	}
	
	public ObjectModel(ArrayList<Point> np){
		_shelllist = np;
	}
	
	
	public int getLoadStatus(){
		return _load;
	}
	
	public void punish(){
		_load = LOAD_NO;
		_hasAni = false;
		_aniType = "";
		_shelllist.clear();
		_alist.clear();
		_color = new RGB(0,0,0);
		_objFile = null;
	}
	
	public boolean hasAni(){
		return _hasAni;
	}
	
	public boolean checkAni(String ani){
		if (_aniType.equals(ani))
			return true;
		else
			return false;
	}
	
	public ArrayList<Point> getShellPoints(){
		return _shelllist;
	}
	
	public ArrayList<Point> getAniPoints(){
		return _alist;
	}
	

	
	public void load(String path){
		_objFile = new File(path);
		load();
	}
	
	private void load(){
		
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder;
		
		try{
			dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(_objFile);
			doc.getDocumentElement().normalize();
			
			if(doc.getDocumentElement().hasChildNodes()){
				if(doc.getDocumentElement().getNodeName().toLowerCase().equals("object")){
					if(doc.getDocumentElement().hasAttribute("connected")){
						String connectedString = doc.getDocumentElement().getAttribute("connected");
						if (connectedString.equals("1")){
							_hasAni = true;
							NodeList rootElement = doc.getDocumentElement().getChildNodes();
							
							for(int i = 0; i < rootElement.getLength(); i++){
								//--COLOR
								if(rootElement.item(i).getNodeName().toLowerCase().equals("color_list")){
									
									NodeList clist = rootElement.item(i).getChildNodes();
									
									for(int j = 0; j < clist.getLength(); j++){
										if (clist.item(j).hasAttributes() && clist.item(j).getNodeName().toLowerCase().equals("border_color")){
											String rString = ((Element) clist.item(j)).getAttribute("r");
											String gString = ((Element) clist.item(j)).getAttribute("g");
											String bString = ((Element) clist.item(j)).getAttribute("b");
											
											int r = Integer.parseInt(rString);
											int g = Integer.parseInt(gString);
											int b = Integer.parseInt(bString);
											
											_color = new RGB(r, g, b);
											
										}
									}
									
								}
								
								//--SHELL POINTS
								if(rootElement.item(i).getNodeName().toLowerCase().indexOf("node_list") == 0){
									NodeList nodeNodeList = rootElement.item(i).getChildNodes();
									
									for(int j = 0; j < nodeNodeList.getLength(); j++){
										if(nodeNodeList.item(j).getNodeName().toLowerCase().indexOf("node") == 0 && nodeNodeList.item(j).hasAttributes()){
											
											String xString = ((Element) nodeNodeList.item(j)).getAttribute("x");
											String yString = ((Element) nodeNodeList.item(j)).getAttribute("y");				
											
											int x = Integer.parseInt(xString);
											int y = Integer.parseInt(yString);
											
											_shelllist.add(new Point(x, y));
										}
									}
									
								}
								
								//--ANISOTROPY
								if(rootElement.item(i).getNodeName().toLowerCase().equals("anisotropy")){
									_aniType = ((Element) rootElement.item(i)).getAttribute("name");	
									
									NodeList alist = rootElement.item(i).getChildNodes();
									
									for(int j = 0; j < alist.getLength(); j++){
										if(alist.item(j).getNodeName().toLowerCase().equals("point")){
											
											String xString = ((Element) alist.item(j)).getAttribute("x");
											String yString = ((Element) alist.item(j)).getAttribute("y");				
											
											int x = Integer.parseInt(xString);
											int y = Integer.parseInt(yString);
											
											_alist.add(new Point(x, y));
											
										}
									}
									
								}
							}
						}

					}
					
	
					
				}
			}
		}
		catch(Exception e){
			e.printStackTrace();
			_hasAni = false;
			_load = LOAD_FAIL;
		}
		
		_load = LOAD_OK;
	
	}
	
	
	
	
	
	
	
	
	
	
	
	public void normalize(){
		if(_shelllist.size() > 0 && _objFile != null){
			
			int x = _shelllist.get(0).x;
			int y = _shelllist.get(0).y;
			
			for(Point p : _shelllist){
				if(p.x < x)
					x = p.x;
				if(p.y < y)
					y = p.y;
			}
			
			System.out.println("Normalize : " + x + "  " + y);
			
			for(Point p : _shelllist){
				p.x = p.x - x;
				p.y = p.y - y;
			}
			
			for(Point p : _alist){
				p.x = p.x - x;
				p.y = p.y - y;
			}
			
		}
	}
	
	
	
	
	
	public Point getMaxCoord(){
		if (_shelllist.size() > 0){
			
			int x = _shelllist.get(0).x;
			int y = _shelllist.get(0).y;
			
			for(Point p : _shelllist){
				if (p.x > x)
					x = p.x;
				if (p.y > y)
					y = p.y;
			}
			
			return new Point(x, y);
			
		}
		else
			return null;
	}
	
	
	public void move(int x, int y){
		
		for(Point p : _shelllist){
			p.x = p.x + x;
			p.y = p.y + y;
		}
		for(Point p : _alist){
			p.x = p.x + x;
			p.y = p.y + y;
		}
		
	}
	

	public Polygon getPolygon(){
		int sz = _shelllist.size();
		
		int x[] = new int[sz];
		int y[] = new int[sz];
		
		for(int i = 0; i < sz; i++){
			x[i] = _shelllist.get(i).x;
			y[i] = _shelllist.get(i).y;
		}
		
		return(new Polygon(x, y, sz));
		
	}
	
	
	
	public Point getRandomAniPoint(){
		
		return _alist.get(0);
		
//		Random r = new Random();
//		int ri = r.nextInt(_alist.size());
//		return _alist.get(ri);
	}
	
	
	public void paint(GC gc){
		
		Color tmp = gc.getBackground();
		Color tmp2 = gc.getForeground();
		
		gc.setBackground(SWTResourceManager.getColor(_color));
		gc.setForeground(SWTResourceManager.getColor(_color));
		
		for(Point p : _shelllist){
			gc.fillPolygon(circle(3, p.x, p.y));
		}
		
		for(int i = 0; i < _shelllist.size()-1; i++){
			gc.drawLine(_shelllist.get(i).x, _shelllist.get(i).y, _shelllist.get(i+1).x, _shelllist.get(i+1).y);
		}
		gc.drawLine(_shelllist.get(0).x, _shelllist.get(0).y, _shelllist.get( _shelllist.size()-1).x, _shelllist.get( _shelllist.size()-1).y);
		
		gc.setBackground(tmp);
		gc.setForeground(tmp2);
	}
	
	
	
	private int[] circle(int r, int offsetX, int offsetY) {
		int[] polygon = new int[8 * r + 4];
		for (int i = 0; i < 2 * r + 1; i++) {
			int x = i - r;
			int y = (int) Math.sqrt(r * r - x * x);
			polygon[2 * i] = offsetX + x;
			polygon[2 * i + 1] = offsetY + y;
			polygon[8 * r - 2 * i - 2] = offsetX + x;
			polygon[8 * r - 2 * i - 1] = offsetY - y;
			}
		return polygon;
	}
	
	
	
}
